{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "Recommender-System-using-Softmax-DNN.ipynb",
      "provenance": [],
      "collapsed_sections": [],
      "authorship_tag": "ABX9TyNEZIZ1oRmoZXi5mI4AT+Ue",
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/rposhala/Recommender-System-on-MovieLens-dataset/blob/main/Recommender_System_using_Softmax_DNN.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "f4dpxTTFCNQi"
      },
      "source": [
        "## Loading the libraries"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "pK__TGE8ABxK"
      },
      "source": [
        "import os\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "import matplotlib.pyplot as plt\n",
        "from sklearn.model_selection import train_test_split\n",
        "from sklearn.preprocessing import LabelEncoder"
      ],
      "execution_count": 1,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "uKKckGQngZKP"
      },
      "source": [
        "# from keras.models import Model\n",
        "# from keras.layers import Input, Reshape, Dot\n",
        "# from keras.layers.embeddings import Embedding\n",
        "# from keras.optimizers import Adam\n",
        "# from keras.regularizers import l2\n",
        "# from keras.layers import Concatenate, Dense, Dropout\n",
        "# from keras.layers import Add, Activation, Lambda\n",
        "\n",
        "import tensorflow as tf\n",
        "import keras\n",
        "from pprint import pprint"
      ],
      "execution_count": 22,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "CEwzA81KOtn8"
      },
      "source": [
        "DATASET_LINK='http://files.grouplens.org/datasets/movielens/ml-100k.zip'"
      ],
      "execution_count": 2,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "_toQkgU7Ot8r",
        "outputId": "e9ca5b39-c7b4-487d-8e0c-f22dbd46787b",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "!wget -nc http://files.grouplens.org/datasets/movielens/ml-100k.zip\n",
        "!unzip -n ml-100k.zip"
      ],
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "--2020-11-14 13:56:35--  http://files.grouplens.org/datasets/movielens/ml-100k.zip\n",
            "Resolving files.grouplens.org (files.grouplens.org)... 128.101.65.152\n",
            "Connecting to files.grouplens.org (files.grouplens.org)|128.101.65.152|:80... connected.\n",
            "HTTP request sent, awaiting response... 200 OK\n",
            "Length: 4924029 (4.7M) [application/zip]\n",
            "Saving to: ‘ml-100k.zip’\n",
            "\n",
            "ml-100k.zip         100%[===================>]   4.70M  16.1MB/s    in 0.3s    \n",
            "\n",
            "2020-11-14 13:56:35 (16.1 MB/s) - ‘ml-100k.zip’ saved [4924029/4924029]\n",
            "\n",
            "Archive:  ml-100k.zip\n",
            "   creating: ml-100k/\n",
            "  inflating: ml-100k/allbut.pl       \n",
            "  inflating: ml-100k/mku.sh          \n",
            "  inflating: ml-100k/README          \n",
            "  inflating: ml-100k/u.data          \n",
            "  inflating: ml-100k/u.genre         \n",
            "  inflating: ml-100k/u.info          \n",
            "  inflating: ml-100k/u.item          \n",
            "  inflating: ml-100k/u.occupation    \n",
            "  inflating: ml-100k/u.user          \n",
            "  inflating: ml-100k/u1.base         \n",
            "  inflating: ml-100k/u1.test         \n",
            "  inflating: ml-100k/u2.base         \n",
            "  inflating: ml-100k/u2.test         \n",
            "  inflating: ml-100k/u3.base         \n",
            "  inflating: ml-100k/u3.test         \n",
            "  inflating: ml-100k/u4.base         \n",
            "  inflating: ml-100k/u4.test         \n",
            "  inflating: ml-100k/u5.base         \n",
            "  inflating: ml-100k/u5.test         \n",
            "  inflating: ml-100k/ua.base         \n",
            "  inflating: ml-100k/ua.test         \n",
            "  inflating: ml-100k/ub.base         \n",
            "  inflating: ml-100k/ub.test         \n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "o7aPc6R_O1S9"
      },
      "source": [
        "#Loading MovieLens dataset"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FZ-rNaLsO8Mj"
      },
      "source": [
        "Loading u.info -- The number of users, items, and ratings in the u data set."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1IV3uY7hOvvF",
        "outputId": "76a13a9a-6b1b-471c-ecc1-d96e21265fc3",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "overall_stats = pd.read_csv('ml-100k/u.info', header=None)\n",
        "print(\"Details of users, items and ratings involved in the loaded movielens dataset: \",list(overall_stats[0]))"
      ],
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Details of users, items and ratings involved in the loaded movielens dataset:  ['943 users', '1682 items', '100000 ratings']\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "pm6F7DFUPPWP"
      },
      "source": [
        "Loading u.data     -- The full u data set, 100000 ratings by 943 users on 1682 items.\n",
        "\n",
        "---\n",
        "\n",
        "\n",
        "\n",
        "              Each user has rated at least 20 movies.  Users and items are\n",
        "              numbered consecutively from 1.  The data is randomly ordered. This is a tab separated list of \n",
        "\t         user id | item id | rating | timestamp. \n",
        "              The time stamps are unix seconds since 1/1/1970 UTC "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "_Dm64PwPO89K",
        "outputId": "0ae36ed1-adf8-4dd7-ac16-8c9473e20eba",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 195
        }
      },
      "source": [
        "## same item id is same as movie id, item id column is renamed as movie id\n",
        "column_names1 = ['user id','movie id','rating','timestamp']\n",
        "ratings_dataset = pd.read_csv('ml-100k/u.data', sep='\\t',header=None,names=column_names1)\n",
        "ratings_dataset.head() "
      ],
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>user id</th>\n",
              "      <th>movie id</th>\n",
              "      <th>rating</th>\n",
              "      <th>timestamp</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>196</td>\n",
              "      <td>242</td>\n",
              "      <td>3</td>\n",
              "      <td>881250949</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>186</td>\n",
              "      <td>302</td>\n",
              "      <td>3</td>\n",
              "      <td>891717742</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>22</td>\n",
              "      <td>377</td>\n",
              "      <td>1</td>\n",
              "      <td>878887116</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>244</td>\n",
              "      <td>51</td>\n",
              "      <td>2</td>\n",
              "      <td>880606923</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>166</td>\n",
              "      <td>346</td>\n",
              "      <td>1</td>\n",
              "      <td>886397596</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "   user id  movie id  rating  timestamp\n",
              "0      196       242       3  881250949\n",
              "1      186       302       3  891717742\n",
              "2       22       377       1  878887116\n",
              "3      244        51       2  880606923\n",
              "4      166       346       1  886397596"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 5
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "PAp4VVTwR6Pz"
      },
      "source": [
        "Loading u.item     -- Information about the items (movies); this is a tab separated\n",
        "\n",
        "              list of\n",
        "              movie id | movie title | release date | video release date |\n",
        "              IMDb URL | unknown | Action | Adventure | Animation |\n",
        "              Children's | Comedy | Crime | Documentary | Drama | Fantasy |\n",
        "              Film-Noir | Horror | Musical | Mystery | Romance | Sci-Fi |\n",
        "              Thriller | War | Western |\n",
        "              The last 19 fields are the genres, a 1 indicates the movie\n",
        "              is of that genre, a 0 indicates it is not; movies can be in\n",
        "              several genres at once.\n",
        "              The movie ids are the ones used in the u.data data set.\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1qxF6i4zRMGj",
        "outputId": "efd387b6-12e4-4520-f634-16143d3e874e",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "d = 'movie id | movie title | release date | video release date | IMDb URL | unknown | Action | Adventure | Animation | Children | Comedy | Crime | Documentary | Drama | Fantasy | Film-Noir | Horror | Musical | Mystery | Romance | Sci-Fi | Thriller | War | Western'\n",
        "column_names2 = d.split(' | ')\n",
        "print(column_names2)"
      ],
      "execution_count": 6,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "['movie id', 'movie title', 'release date', 'video release date', 'IMDb URL', 'unknown', 'Action', 'Adventure', 'Animation', 'Children', 'Comedy', 'Crime', 'Documentary', 'Drama', 'Fantasy', 'Film-Noir', 'Horror', 'Musical', 'Mystery', 'Romance', 'Sci-Fi', 'Thriller', 'War', 'Western']\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "fZKhPm9dRqvR",
        "outputId": "44f3ae94-9e6d-4da4-d9d0-1596f6de2699",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 366
        }
      },
      "source": [
        "items_dataset = pd.read_csv('ml-100k/u.item', sep='|',header=None,names=column_names2,encoding='latin-1')\n",
        "items_dataset.head()"
      ],
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>movie id</th>\n",
              "      <th>movie title</th>\n",
              "      <th>release date</th>\n",
              "      <th>video release date</th>\n",
              "      <th>IMDb URL</th>\n",
              "      <th>unknown</th>\n",
              "      <th>Action</th>\n",
              "      <th>Adventure</th>\n",
              "      <th>Animation</th>\n",
              "      <th>Children</th>\n",
              "      <th>Comedy</th>\n",
              "      <th>Crime</th>\n",
              "      <th>Documentary</th>\n",
              "      <th>Drama</th>\n",
              "      <th>Fantasy</th>\n",
              "      <th>Film-Noir</th>\n",
              "      <th>Horror</th>\n",
              "      <th>Musical</th>\n",
              "      <th>Mystery</th>\n",
              "      <th>Romance</th>\n",
              "      <th>Sci-Fi</th>\n",
              "      <th>Thriller</th>\n",
              "      <th>War</th>\n",
              "      <th>Western</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>1</td>\n",
              "      <td>Toy Story (1995)</td>\n",
              "      <td>01-Jan-1995</td>\n",
              "      <td>NaN</td>\n",
              "      <td>http://us.imdb.com/M/title-exact?Toy%20Story%2...</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>1</td>\n",
              "      <td>1</td>\n",
              "      <td>1</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>2</td>\n",
              "      <td>GoldenEye (1995)</td>\n",
              "      <td>01-Jan-1995</td>\n",
              "      <td>NaN</td>\n",
              "      <td>http://us.imdb.com/M/title-exact?GoldenEye%20(...</td>\n",
              "      <td>0</td>\n",
              "      <td>1</td>\n",
              "      <td>1</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>1</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>3</td>\n",
              "      <td>Four Rooms (1995)</td>\n",
              "      <td>01-Jan-1995</td>\n",
              "      <td>NaN</td>\n",
              "      <td>http://us.imdb.com/M/title-exact?Four%20Rooms%...</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>1</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>4</td>\n",
              "      <td>Get Shorty (1995)</td>\n",
              "      <td>01-Jan-1995</td>\n",
              "      <td>NaN</td>\n",
              "      <td>http://us.imdb.com/M/title-exact?Get%20Shorty%...</td>\n",
              "      <td>0</td>\n",
              "      <td>1</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>1</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>1</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>5</td>\n",
              "      <td>Copycat (1995)</td>\n",
              "      <td>01-Jan-1995</td>\n",
              "      <td>NaN</td>\n",
              "      <td>http://us.imdb.com/M/title-exact?Copycat%20(1995)</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>1</td>\n",
              "      <td>0</td>\n",
              "      <td>1</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>1</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "   movie id        movie title release date  ...  Thriller War  Western\n",
              "0         1   Toy Story (1995)  01-Jan-1995  ...         0   0        0\n",
              "1         2   GoldenEye (1995)  01-Jan-1995  ...         1   0        0\n",
              "2         3  Four Rooms (1995)  01-Jan-1995  ...         1   0        0\n",
              "3         4  Get Shorty (1995)  01-Jan-1995  ...         0   0        0\n",
              "4         5     Copycat (1995)  01-Jan-1995  ...         1   0        0\n",
              "\n",
              "[5 rows x 24 columns]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 7
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "zjMViWz_SDlJ",
        "outputId": "3fa38eec-61c4-41c7-c363-cbcbaebee253",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 195
        }
      },
      "source": [
        "movie_dataset = items_dataset[['movie id','movie title']]\n",
        "movie_dataset.head()"
      ],
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>movie id</th>\n",
              "      <th>movie title</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>1</td>\n",
              "      <td>Toy Story (1995)</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>2</td>\n",
              "      <td>GoldenEye (1995)</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>3</td>\n",
              "      <td>Four Rooms (1995)</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>4</td>\n",
              "      <td>Get Shorty (1995)</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>5</td>\n",
              "      <td>Copycat (1995)</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "   movie id        movie title\n",
              "0         1   Toy Story (1995)\n",
              "1         2   GoldenEye (1995)\n",
              "2         3  Four Rooms (1995)\n",
              "3         4  Get Shorty (1995)\n",
              "4         5     Copycat (1995)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 8
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "hEsztTxjSiZA"
      },
      "source": [
        "Looking at length of original items_dataset and length of unique combination of rows in items_dataset after removing movie id column"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "sdzz8nUySG_q",
        "outputId": "a0fe00d3-23c4-4125-89fa-b3be9bea9c2e",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "## looking at length of original items_dataset and length of unique combination of rows in items_dataset after removing movie id column\n",
        "len(items_dataset.groupby(by=column_names2[1:])),len(items_dataset)"
      ],
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(1664, 1682)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 9
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "zcsMvVNrS82A"
      },
      "source": [
        "We can see there are 18 extra movie id's for already mapped movie title and the same duplicate movie id is assigned to the user in the user-item dataset."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "V1vln0JRTA9J"
      },
      "source": [
        "#Merging required datasets"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "IBOXHTmvS6Ex",
        "outputId": "c9995cf4-c7fd-47b0-afb7-c57b7fce007c",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 195
        }
      },
      "source": [
        "merged_dataset = pd.merge(ratings_dataset, movie_dataset, how='inner', on='movie id')\n",
        "merged_dataset.head()"
      ],
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>user id</th>\n",
              "      <th>movie id</th>\n",
              "      <th>rating</th>\n",
              "      <th>timestamp</th>\n",
              "      <th>movie title</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>196</td>\n",
              "      <td>242</td>\n",
              "      <td>3</td>\n",
              "      <td>881250949</td>\n",
              "      <td>Kolya (1996)</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>63</td>\n",
              "      <td>242</td>\n",
              "      <td>3</td>\n",
              "      <td>875747190</td>\n",
              "      <td>Kolya (1996)</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>226</td>\n",
              "      <td>242</td>\n",
              "      <td>5</td>\n",
              "      <td>883888671</td>\n",
              "      <td>Kolya (1996)</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>154</td>\n",
              "      <td>242</td>\n",
              "      <td>3</td>\n",
              "      <td>879138235</td>\n",
              "      <td>Kolya (1996)</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>306</td>\n",
              "      <td>242</td>\n",
              "      <td>5</td>\n",
              "      <td>876503793</td>\n",
              "      <td>Kolya (1996)</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "   user id  movie id  rating  timestamp   movie title\n",
              "0      196       242       3  881250949  Kolya (1996)\n",
              "1       63       242       3  875747190  Kolya (1996)\n",
              "2      226       242       5  883888671  Kolya (1996)\n",
              "3      154       242       3  879138235  Kolya (1996)\n",
              "4      306       242       5  876503793  Kolya (1996)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 10
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qlTqLn-mTUCV"
      },
      "source": [
        "A dataset is created from the existing merged dataset by grouping the unique user id and movie title combination and the ratings by a user to the same movie in different instances (timestamps) are averaged and stored in the new dataset."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "U6wjxXe7TeIO"
      },
      "source": [
        "Example of a multiple rating scenario by an user to a specific movie:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "xKgq_aXmTDft",
        "outputId": "a2c48fbb-150a-4765-c54c-7be66c36751c",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 106
        }
      },
      "source": [
        "merged_dataset[(merged_dataset['movie title'] == 'Chasing Amy (1997)') & (merged_dataset['user id'] == 894)]"
      ],
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>user id</th>\n",
              "      <th>movie id</th>\n",
              "      <th>rating</th>\n",
              "      <th>timestamp</th>\n",
              "      <th>movie title</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>4800</th>\n",
              "      <td>894</td>\n",
              "      <td>246</td>\n",
              "      <td>4</td>\n",
              "      <td>882404137</td>\n",
              "      <td>Chasing Amy (1997)</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>22340</th>\n",
              "      <td>894</td>\n",
              "      <td>268</td>\n",
              "      <td>3</td>\n",
              "      <td>879896041</td>\n",
              "      <td>Chasing Amy (1997)</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "       user id  movie id  rating  timestamp         movie title\n",
              "4800       894       246       4  882404137  Chasing Amy (1997)\n",
              "22340      894       268       3  879896041  Chasing Amy (1997)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 11
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "kuXOfYN-UQrP"
      },
      "source": [
        "## Creating a final refined dataset with unique user id, movie name combination and their ratings:\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "gSybgvihTkgE",
        "outputId": "e43e9262-bca7-4c1c-c238-a47ca4d01303",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 195
        }
      },
      "source": [
        "refined_dataset = merged_dataset.groupby(by=['user id','movie title'], as_index=False).agg({\"rating\":\"mean\"})\n",
        "\n",
        "refined_dataset.head()"
      ],
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>user id</th>\n",
              "      <th>movie title</th>\n",
              "      <th>rating</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>1</td>\n",
              "      <td>101 Dalmatians (1996)</td>\n",
              "      <td>2.0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>1</td>\n",
              "      <td>12 Angry Men (1957)</td>\n",
              "      <td>5.0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>1</td>\n",
              "      <td>20,000 Leagues Under the Sea (1954)</td>\n",
              "      <td>3.0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>1</td>\n",
              "      <td>2001: A Space Odyssey (1968)</td>\n",
              "      <td>4.0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>1</td>\n",
              "      <td>Abyss, The (1989)</td>\n",
              "      <td>3.0</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "   user id                          movie title  rating\n",
              "0        1                101 Dalmatians (1996)     2.0\n",
              "1        1                  12 Angry Men (1957)     5.0\n",
              "2        1  20,000 Leagues Under the Sea (1954)     3.0\n",
              "3        1         2001: A Space Odyssey (1968)     4.0\n",
              "4        1                    Abyss, The (1989)     3.0"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 12
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "OVuuEkazUn20"
      },
      "source": [
        "## Encoding users and movie titles to make sure that the sequence has no missing values when dealing with Deep Neural Networks."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "-X1Fvj3AUTjt"
      },
      "source": [
        "user_enc = LabelEncoder()\n",
        "refined_dataset['user'] = user_enc.fit_transform(refined_dataset['user id'].values)\n",
        "n_users = refined_dataset['user'].nunique()"
      ],
      "execution_count": 13,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "3f2vtjifW662"
      },
      "source": [
        "item_enc = LabelEncoder()\n",
        "refined_dataset['movie'] = item_enc.fit_transform(refined_dataset['movie title'].values)\n",
        "n_movies = refined_dataset['movie'].nunique()"
      ],
      "execution_count": 14,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "OeQb6BDbXUzI",
        "outputId": "9db3aaae-b877-4ce0-8e39-726b3de57384",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "refined_dataset['rating'] = refined_dataset['rating'].values.astype(np.float32)\n",
        "min_rating = min(refined_dataset['rating'])\n",
        "max_rating = max(refined_dataset['rating'])\n",
        "n_users, n_movies, min_rating, max_rating"
      ],
      "execution_count": 15,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(943, 1664, 1.0, 5.0)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 15
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "2NLsO6VSXOD4",
        "outputId": "2ad334e6-8823-4104-bfe4-5b3554063252",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 195
        }
      },
      "source": [
        "refined_dataset.head()"
      ],
      "execution_count": 16,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>user id</th>\n",
              "      <th>movie title</th>\n",
              "      <th>rating</th>\n",
              "      <th>user</th>\n",
              "      <th>movie</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>1</td>\n",
              "      <td>101 Dalmatians (1996)</td>\n",
              "      <td>2.0</td>\n",
              "      <td>0</td>\n",
              "      <td>2</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>1</td>\n",
              "      <td>12 Angry Men (1957)</td>\n",
              "      <td>5.0</td>\n",
              "      <td>0</td>\n",
              "      <td>3</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>1</td>\n",
              "      <td>20,000 Leagues Under the Sea (1954)</td>\n",
              "      <td>3.0</td>\n",
              "      <td>0</td>\n",
              "      <td>6</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>1</td>\n",
              "      <td>2001: A Space Odyssey (1968)</td>\n",
              "      <td>4.0</td>\n",
              "      <td>0</td>\n",
              "      <td>7</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>1</td>\n",
              "      <td>Abyss, The (1989)</td>\n",
              "      <td>3.0</td>\n",
              "      <td>0</td>\n",
              "      <td>16</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "   user id                          movie title  rating  user  movie\n",
              "0        1                101 Dalmatians (1996)     2.0     0      2\n",
              "1        1                  12 Angry Men (1957)     5.0     0      3\n",
              "2        1  20,000 Leagues Under the Sea (1954)     3.0     0      6\n",
              "3        1         2001: A Space Odyssey (1968)     4.0     0      7\n",
              "4        1                    Abyss, The (1989)     3.0     0     16"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 16
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "3Vrfgd7TZ08C"
      },
      "source": [
        "## Splitting the data into training and testing"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "9q04V-GnXPFs",
        "outputId": "efadf08a-206e-4d4f-dd06-17b44fa8f693",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "X = refined_dataset[['user', 'movie']].values\n",
        "y = refined_dataset['rating'].values\n",
        "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=50)\n",
        "X_train.shape, X_test.shape, y_train.shape, y_test.shape"
      ],
      "execution_count": 17,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "((89723, 2), (9970, 2), (89723,), (9970,))"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 17
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "y3s3cccxgGPy"
      },
      "source": [
        "## Defining number of factors which are to be considered by the Embedding layer"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "zA39k64MaEfs"
      },
      "source": [
        "n_factors = 150"
      ],
      "execution_count": 23,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "fcqGOsdZgaFY"
      },
      "source": [
        "Columns in the input array are split into two separate arrays. As Keras considers them as two distinct inputs, each input needs to be fed in as its own array."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "83v-ulEIgS1l"
      },
      "source": [
        "X_train_array = [X_train[:, 0], X_train[:, 1]]\n",
        "X_test_array = [X_test[:, 0], X_test[:, 1]]"
      ],
      "execution_count": 19,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "OpCiDWkexTkf",
        "outputId": "1a4a2766-39ef-4fd8-e9f0-535947aae7dd",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "X_train, X_train_array, X_train_array[0].shape"
      ],
      "execution_count": 20,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(array([[ 180, 1152],\n",
              "        [ 487,  389],\n",
              "        [ 177,  302],\n",
              "        ...,\n",
              "        [ 431, 1588],\n",
              "        [ 232,  399],\n",
              "        [ 138,  612]]),\n",
              " [array([180, 487, 177, ..., 431, 232, 138]),\n",
              "  array([1152,  389,  302, ..., 1588,  399,  612])],\n",
              " (89723,))"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 20
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "fgdqWxK1IDAg"
      },
      "source": [
        "## Normalizing the labels"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "4POYLlXTIP7G"
      },
      "source": [
        "\n",
        "y_train = (y_train - min_rating)/(max_rating - min_rating)\n",
        "y_test = (y_test - min_rating)/(max_rating - min_rating)"
      ],
      "execution_count": 21,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "C_sQMkI-m-i-"
      },
      "source": [
        "## Building a Softmax Deep Neural Network"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "PRBTogiuhpmV"
      },
      "source": [
        "## Initializing a input layer for users\n",
        "user = tf.keras.layers.Input(shape = (1,))\n",
        "\n",
        "## Embedding layer for n_factors of users\n",
        "u = keras.layers.embeddings.Embedding(n_users, n_factors, embeddings_initializer = 'he_normal', embeddings_regularizer = tf.keras.regularizers.l2(1e-6))(user)\n",
        "u = tf.keras.layers.Reshape((n_factors,))(u)\n",
        "\n",
        "## Initializing a input layer for movies\n",
        "movie = tf.keras.layers.Input(shape = (1,))\n",
        "\n",
        "## Embedding layer for n_factors of movies\n",
        "m = keras.layers.embeddings.Embedding(n_movies, n_factors, embeddings_initializer = 'he_normal', embeddings_regularizer=tf.keras.regularizers.l2(1e-6))(movie)\n",
        "m = tf.keras.layers.Reshape((n_factors,))(m)\n",
        "\n",
        "## stacking up both user and movie embeddings\n",
        "x = tf.keras.layers.Concatenate()([u,m])\n",
        "x = tf.keras.layers.Dropout(0.05)(x)\n",
        "\n",
        "## Adding a Dense layer to the architecture\n",
        "x = tf.keras.layers.Dense(32, kernel_initializer='he_normal')(x)\n",
        "x = tf.keras.layers.Activation(activation='relu')(x)\n",
        "x = tf.keras.layers.Dropout(0.05)(x)\n",
        "\n",
        "x = tf.keras.layers.Dense(16, kernel_initializer='he_normal')(x)\n",
        "x = tf.keras.layers.Activation(activation='relu')(x)\n",
        "x = tf.keras.layers.Dropout(0.05)(x)\n",
        "\n",
        "## Adding an Output layer with Sigmoid activation funtion which gives output between 0 and 1\n",
        "x = tf.keras.layers.Dense(9)(x)\n",
        "x = tf.keras.layers.Activation(activation='softmax')(x)\n",
        "\n",
        "## Adding a Lambda layer to convert the output to rating by scaling it with the help of available rating information\n",
        "# x = tf.keras.layers.Lambda(lambda x: x*(max_rating - min_rating) + min_rating)(x)\n",
        "\n",
        "## Defining the model\n",
        "model = tf.keras.models.Model(inputs=[user,movie], outputs=x)\n",
        "# optimizer = tf.keras.optimizers.Adam(lr=0.001)\n",
        "# optimizer = tf.keras.optimizers.RMSprop(learning_rate=0.005,\n",
        "    # rho=0.9, momentum=0.01, epsilon=1e-07)\n",
        "\n",
        "## Compiling the model\n",
        "# model.compile(loss='binary_crossentropy', optimizer = optimizer)\n",
        "# model.compile(loss='mean_squared_error', optimizer = optimizer,metrics=['accuracy'])\n",
        "model.compile(optimizer='sgd', loss=tf.keras.losses.SparseCategoricalCrossentropy(), metrics=['accuracy'])\n"
      ],
      "execution_count": 30,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "7rMMb03YpJt-",
        "outputId": "4a55230d-c639-4c04-c997-4317d3dd8693",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "model.summary()"
      ],
      "execution_count": 31,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Model: \"functional_5\"\n",
            "__________________________________________________________________________________________________\n",
            "Layer (type)                    Output Shape         Param #     Connected to                     \n",
            "==================================================================================================\n",
            "input_5 (InputLayer)            [(None, 1)]          0                                            \n",
            "__________________________________________________________________________________________________\n",
            "input_6 (InputLayer)            [(None, 1)]          0                                            \n",
            "__________________________________________________________________________________________________\n",
            "embedding_4 (Embedding)         (None, 1, 150)       141450      input_5[0][0]                    \n",
            "__________________________________________________________________________________________________\n",
            "embedding_5 (Embedding)         (None, 1, 150)       249600      input_6[0][0]                    \n",
            "__________________________________________________________________________________________________\n",
            "reshape_4 (Reshape)             (None, 150)          0           embedding_4[0][0]                \n",
            "__________________________________________________________________________________________________\n",
            "reshape_5 (Reshape)             (None, 150)          0           embedding_5[0][0]                \n",
            "__________________________________________________________________________________________________\n",
            "concatenate_2 (Concatenate)     (None, 300)          0           reshape_4[0][0]                  \n",
            "                                                                 reshape_5[0][0]                  \n",
            "__________________________________________________________________________________________________\n",
            "dropout_6 (Dropout)             (None, 300)          0           concatenate_2[0][0]              \n",
            "__________________________________________________________________________________________________\n",
            "dense_6 (Dense)                 (None, 32)           9632        dropout_6[0][0]                  \n",
            "__________________________________________________________________________________________________\n",
            "activation_6 (Activation)       (None, 32)           0           dense_6[0][0]                    \n",
            "__________________________________________________________________________________________________\n",
            "dropout_7 (Dropout)             (None, 32)           0           activation_6[0][0]               \n",
            "__________________________________________________________________________________________________\n",
            "dense_7 (Dense)                 (None, 16)           528         dropout_7[0][0]                  \n",
            "__________________________________________________________________________________________________\n",
            "activation_7 (Activation)       (None, 16)           0           dense_7[0][0]                    \n",
            "__________________________________________________________________________________________________\n",
            "dropout_8 (Dropout)             (None, 16)           0           activation_7[0][0]               \n",
            "__________________________________________________________________________________________________\n",
            "dense_8 (Dense)                 (None, 9)            153         dropout_8[0][0]                  \n",
            "__________________________________________________________________________________________________\n",
            "activation_8 (Activation)       (None, 9)            0           dense_8[0][0]                    \n",
            "==================================================================================================\n",
            "Total params: 401,363\n",
            "Trainable params: 401,363\n",
            "Non-trainable params: 0\n",
            "__________________________________________________________________________________________________\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Ky7cKIGDuSgy",
        "outputId": "636e86b7-702a-4047-d8c0-d30c8e47df47",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.75, patience=3, min_lr=0.000001, verbose=1)\n",
        "\n",
        "history = model.fit(x = X_train_array, y = y_train, batch_size=128, epochs=70, verbose=1, validation_data=(X_test_array, y_test)\n",
        ",shuffle=True,callbacks=[reduce_lr])\n"
      ],
      "execution_count": 32,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Epoch 1/70\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/indexed_slices.py:432: UserWarning: Converting sparse IndexedSlices to a dense Tensor of unknown shape. This may consume a large amount of memory.\n",
            "  \"Converting sparse IndexedSlices to a dense Tensor of unknown shape. \"\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "stream",
          "text": [
            "701/701 [==============================] - 4s 5ms/step - loss: 0.8508 - accuracy: 0.0608 - val_loss: 0.5331 - val_accuracy: 0.0617\n",
            "Epoch 2/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5358 - accuracy: 0.0609 - val_loss: 0.5159 - val_accuracy: 0.0617\n",
            "Epoch 3/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5253 - accuracy: 0.0609 - val_loss: 0.5125 - val_accuracy: 0.0617\n",
            "Epoch 4/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5222 - accuracy: 0.0609 - val_loss: 0.5114 - val_accuracy: 0.0617\n",
            "Epoch 5/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5207 - accuracy: 0.0609 - val_loss: 0.5114 - val_accuracy: 0.0617\n",
            "Epoch 6/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5201 - accuracy: 0.0609 - val_loss: 0.5106 - val_accuracy: 0.0617\n",
            "Epoch 7/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5193 - accuracy: 0.0609 - val_loss: 0.5102 - val_accuracy: 0.0617\n",
            "Epoch 8/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5187 - accuracy: 0.0609 - val_loss: 0.5112 - val_accuracy: 0.0617\n",
            "Epoch 9/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5188 - accuracy: 0.0609 - val_loss: 0.5098 - val_accuracy: 0.0617\n",
            "Epoch 10/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5181 - accuracy: 0.0609 - val_loss: 0.5097 - val_accuracy: 0.0617\n",
            "Epoch 11/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5180 - accuracy: 0.0609 - val_loss: 0.5091 - val_accuracy: 0.0617\n",
            "Epoch 12/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5176 - accuracy: 0.0609 - val_loss: 0.5088 - val_accuracy: 0.0617\n",
            "Epoch 13/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5171 - accuracy: 0.0609 - val_loss: 0.5096 - val_accuracy: 0.0617\n",
            "Epoch 14/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5168 - accuracy: 0.0609 - val_loss: 0.5082 - val_accuracy: 0.0617\n",
            "Epoch 15/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5162 - accuracy: 0.0609 - val_loss: 0.5076 - val_accuracy: 0.0617\n",
            "Epoch 16/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5157 - accuracy: 0.0609 - val_loss: 0.5066 - val_accuracy: 0.0617\n",
            "Epoch 17/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5149 - accuracy: 0.0609 - val_loss: 0.5058 - val_accuracy: 0.0617\n",
            "Epoch 18/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5141 - accuracy: 0.0609 - val_loss: 0.5051 - val_accuracy: 0.0617\n",
            "Epoch 19/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5129 - accuracy: 0.0609 - val_loss: 0.5035 - val_accuracy: 0.0617\n",
            "Epoch 20/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5117 - accuracy: 0.0609 - val_loss: 0.5021 - val_accuracy: 0.0617\n",
            "Epoch 21/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5101 - accuracy: 0.0609 - val_loss: 0.5005 - val_accuracy: 0.0617\n",
            "Epoch 22/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5077 - accuracy: 0.0609 - val_loss: 0.4976 - val_accuracy: 0.0617\n",
            "Epoch 23/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5057 - accuracy: 0.0609 - val_loss: 0.4945 - val_accuracy: 0.0617\n",
            "Epoch 24/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.5025 - accuracy: 0.0609 - val_loss: 0.4908 - val_accuracy: 0.0617\n",
            "Epoch 25/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4982 - accuracy: 0.0609 - val_loss: 0.4862 - val_accuracy: 0.0617\n",
            "Epoch 26/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4935 - accuracy: 0.0609 - val_loss: 0.4806 - val_accuracy: 0.0617\n",
            "Epoch 27/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4880 - accuracy: 0.0609 - val_loss: 0.4744 - val_accuracy: 0.0617\n",
            "Epoch 28/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4817 - accuracy: 0.0609 - val_loss: 0.4689 - val_accuracy: 0.0617\n",
            "Epoch 29/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4748 - accuracy: 0.0609 - val_loss: 0.4629 - val_accuracy: 0.0617\n",
            "Epoch 30/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4688 - accuracy: 0.0609 - val_loss: 0.4558 - val_accuracy: 0.0617\n",
            "Epoch 31/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4627 - accuracy: 0.0610 - val_loss: 0.4506 - val_accuracy: 0.0617\n",
            "Epoch 32/70\n",
            "701/701 [==============================] - 4s 5ms/step - loss: 0.4574 - accuracy: 0.0619 - val_loss: 0.4464 - val_accuracy: 0.0617\n",
            "Epoch 33/70\n",
            "701/701 [==============================] - 4s 5ms/step - loss: 0.4526 - accuracy: 0.0657 - val_loss: 0.4426 - val_accuracy: 0.0617\n",
            "Epoch 34/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4492 - accuracy: 0.0759 - val_loss: 0.4395 - val_accuracy: 0.0736\n",
            "Epoch 35/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4447 - accuracy: 0.0835 - val_loss: 0.4368 - val_accuracy: 0.0790\n",
            "Epoch 36/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4414 - accuracy: 0.0870 - val_loss: 0.4344 - val_accuracy: 0.0896\n",
            "Epoch 37/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4386 - accuracy: 0.0946 - val_loss: 0.4328 - val_accuracy: 0.0962\n",
            "Epoch 38/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4355 - accuracy: 0.0986 - val_loss: 0.4309 - val_accuracy: 0.0964\n",
            "Epoch 39/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4332 - accuracy: 0.1010 - val_loss: 0.4303 - val_accuracy: 0.1120\n",
            "Epoch 40/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4310 - accuracy: 0.1053 - val_loss: 0.4281 - val_accuracy: 0.1036\n",
            "Epoch 41/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4297 - accuracy: 0.1076 - val_loss: 0.4276 - val_accuracy: 0.1107\n",
            "Epoch 42/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4276 - accuracy: 0.1085 - val_loss: 0.4259 - val_accuracy: 0.1131\n",
            "Epoch 43/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4261 - accuracy: 0.1131 - val_loss: 0.4272 - val_accuracy: 0.1214\n",
            "Epoch 44/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4243 - accuracy: 0.1109 - val_loss: 0.4242 - val_accuracy: 0.1104\n",
            "Epoch 45/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4231 - accuracy: 0.1139 - val_loss: 0.4235 - val_accuracy: 0.1058\n",
            "Epoch 46/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4217 - accuracy: 0.1168 - val_loss: 0.4230 - val_accuracy: 0.1102\n",
            "Epoch 47/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4211 - accuracy: 0.1168 - val_loss: 0.4227 - val_accuracy: 0.1225\n",
            "Epoch 48/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4202 - accuracy: 0.1204 - val_loss: 0.4225 - val_accuracy: 0.1203\n",
            "Epoch 49/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4183 - accuracy: 0.1194 - val_loss: 0.4211 - val_accuracy: 0.1154\n",
            "Epoch 50/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4174 - accuracy: 0.1211 - val_loss: 0.4212 - val_accuracy: 0.1232\n",
            "Epoch 51/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4173 - accuracy: 0.1208 - val_loss: 0.4205 - val_accuracy: 0.1214\n",
            "Epoch 52/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4167 - accuracy: 0.1222 - val_loss: 0.4203 - val_accuracy: 0.1234\n",
            "Epoch 53/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4149 - accuracy: 0.1230 - val_loss: 0.4198 - val_accuracy: 0.1237\n",
            "Epoch 54/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4141 - accuracy: 0.1252 - val_loss: 0.4194 - val_accuracy: 0.1188\n",
            "Epoch 55/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4136 - accuracy: 0.1235 - val_loss: 0.4189 - val_accuracy: 0.1170\n",
            "Epoch 56/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4136 - accuracy: 0.1245 - val_loss: 0.4187 - val_accuracy: 0.1176\n",
            "Epoch 57/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4130 - accuracy: 0.1239 - val_loss: 0.4185 - val_accuracy: 0.1178\n",
            "Epoch 58/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4116 - accuracy: 0.1247 - val_loss: 0.4182 - val_accuracy: 0.1237\n",
            "Epoch 59/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4107 - accuracy: 0.1257 - val_loss: 0.4181 - val_accuracy: 0.1244\n",
            "Epoch 60/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4111 - accuracy: 0.1265 - val_loss: 0.4182 - val_accuracy: 0.1281\n",
            "Epoch 61/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4107 - accuracy: 0.1258 - val_loss: 0.4176 - val_accuracy: 0.1157\n",
            "Epoch 62/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4098 - accuracy: 0.1264 - val_loss: 0.4178 - val_accuracy: 0.1183\n",
            "Epoch 63/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4097 - accuracy: 0.1267 - val_loss: 0.4174 - val_accuracy: 0.1254\n",
            "Epoch 64/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4096 - accuracy: 0.1277 - val_loss: 0.4180 - val_accuracy: 0.1314\n",
            "Epoch 65/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4084 - accuracy: 0.1289 - val_loss: 0.4170 - val_accuracy: 0.1220\n",
            "Epoch 66/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4087 - accuracy: 0.1274 - val_loss: 0.4174 - val_accuracy: 0.1254\n",
            "Epoch 67/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4078 - accuracy: 0.1277 - val_loss: 0.4172 - val_accuracy: 0.1268\n",
            "Epoch 68/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4070 - accuracy: 0.1287 - val_loss: 0.4169 - val_accuracy: 0.1194\n",
            "Epoch 69/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4071 - accuracy: 0.1287 - val_loss: 0.4170 - val_accuracy: 0.1273\n",
            "Epoch 70/70\n",
            "701/701 [==============================] - 3s 5ms/step - loss: 0.4063 - accuracy: 0.1286 - val_loss: 0.4171 - val_accuracy: 0.1305\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Ia_EsnKTur47",
        "outputId": "6e91d112-687e-49a5-9cf3-83395510bfa2",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 295
        }
      },
      "source": [
        "plt.plot(history.history[\"loss\"][5:])\n",
        "plt.plot(history.history[\"val_loss\"][5:])\n",
        "plt.title(\"model loss\")\n",
        "plt.ylabel(\"loss\")\n",
        "plt.xlabel(\"epoch\")\n",
        "plt.legend([\"train\", \"test\"], loc=\"upper left\")\n",
        "plt.show()"
      ],
      "execution_count": 33,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "2VpBSnCPILno"
      },
      "source": [
        "## Getting movies for given User"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "qRgSHldIJMLu",
        "outputId": "63f27ff6-1c88-4d8f-ddfa-18e84971bb58",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 195
        }
      },
      "source": [
        "refined_dataset.head()"
      ],
      "execution_count": 34,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>user id</th>\n",
              "      <th>movie title</th>\n",
              "      <th>rating</th>\n",
              "      <th>user</th>\n",
              "      <th>movie</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>1</td>\n",
              "      <td>101 Dalmatians (1996)</td>\n",
              "      <td>2.0</td>\n",
              "      <td>0</td>\n",
              "      <td>2</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>1</td>\n",
              "      <td>12 Angry Men (1957)</td>\n",
              "      <td>5.0</td>\n",
              "      <td>0</td>\n",
              "      <td>3</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>1</td>\n",
              "      <td>20,000 Leagues Under the Sea (1954)</td>\n",
              "      <td>3.0</td>\n",
              "      <td>0</td>\n",
              "      <td>6</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>1</td>\n",
              "      <td>2001: A Space Odyssey (1968)</td>\n",
              "      <td>4.0</td>\n",
              "      <td>0</td>\n",
              "      <td>7</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>1</td>\n",
              "      <td>Abyss, The (1989)</td>\n",
              "      <td>3.0</td>\n",
              "      <td>0</td>\n",
              "      <td>16</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "   user id                          movie title  rating  user  movie\n",
              "0        1                101 Dalmatians (1996)     2.0     0      2\n",
              "1        1                  12 Angry Men (1957)     5.0     0      3\n",
              "2        1  20,000 Leagues Under the Sea (1954)     3.0     0      6\n",
              "3        1         2001: A Space Odyssey (1968)     4.0     0      7\n",
              "4        1                    Abyss, The (1989)     3.0     0     16"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 34
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Xdmw3s6eJjSz"
      },
      "source": [
        "**How this DNN model works is, it takes two inputs, one of the input has user id's and the other has corresponding movie id's. Here DNN model tries to predict the ratings of the user - movie combination. So, we can input a specific user id (broadcasting it with the size of other input) and unseen movie id of the user and expect the model to give the ratings of the movies which would have been the ratings given by the user. Here, the ratings are already normalized and as we need the movies which interest the user more, ratings are not brought back to 0-5 scale.**"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "A9pFADxRM-SX",
        "outputId": "094cda8f-f537-40f8-a4bb-081f1609debc",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "X_train_array"
      ],
      "execution_count": 40,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[array([180, 487, 177, ..., 431, 232, 138]),\n",
              " array([1152,  389,  302, ..., 1588,  399,  612])]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 40
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "_5Orqr2yatoT"
      },
      "source": [
        "Above is the model input shape"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "bKuwDF7pxEgA",
        "outputId": "d87ddc00-2d77-467b-e969-a178b6915885",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "\n",
        "user_id = [777]\n",
        "encoded_user_id = user_enc.transform(user_id)\n",
        "\n",
        "seen_movies = list(refined_dataset[refined_dataset['user id'] == user_id[0]]['movie'])\n",
        "print(seen_movies)"
      ],
      "execution_count": 62,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "[7, 55, 87, 113, 313, 337, 389, 390, 399, 411, 432, 460, 498, 528, 580, 604, 612, 643, 666, 783, 996, 1005, 1032, 1102, 1132, 1157, 1190, 1208, 1251, 1260, 1284, 1302, 1342, 1523, 1558, 1615]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "_qMqFifba4Yj"
      },
      "source": [
        "Id's of movies which are already seen by the user are extracted."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "IjXFgDR4NTkO",
        "outputId": "5d0f7e81-0a74-4937-9d5f-e6bae0b1a710",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "len(refined_dataset['movie'].unique()), min(refined_dataset['movie']), max(refined_dataset['movie'])"
      ],
      "execution_count": 67,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(1664, 0, 1663)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 67
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Np6LcHMwYTD-"
      },
      "source": [
        "We can understand that the labels are from 0 to 1663. So the movie id's which are not seen by the user can be pciked just by excluding the 'seen_movies' list from the first 1663 natural numbers."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "i_rRA2ScWFLF",
        "outputId": "91e243ff-bb18-40ca-ca25-b6bbdcbdaa6a",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "unseen_movies = [i for i in range(min(refined_dataset['movie']), max(refined_dataset['movie'])+1) if i not in seen_movies]\n",
        "print(unseen_movies)"
      ],
      "execution_count": 72,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "[0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,....., 1637, 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "KcspS9SMdJef"
      },
      "source": [
        "Movies which are not seen by the user."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "mtCDRu3WYCZa",
        "outputId": "48021904-8448-4a42-8503-12ac87cca357",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "len(unseen_movies) + len(seen_movies)"
      ],
      "execution_count": 74,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "1664"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 74
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "qmS6oeujY6fo",
        "outputId": "c0bb5729-431b-47ff-f80c-a5ce7a204206",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "model_input = [np.asarray(list(encoded_user_id)*len(unseen_movies)), np.asarray(unseen_movies)]\n",
        "len(model_input), len(model_input[0])"
      ],
      "execution_count": 92,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(2, 1628)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 92
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "PyRgI_vJdsAp"
      },
      "source": [
        "**DNN model is used to predict the ratings of the unseen movies.**"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "mmtIZjAgZSax"
      },
      "source": [
        "predicted_ratings = model.predict(model_input)"
      ],
      "execution_count": 84,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "OfKQOn9CZhi9",
        "outputId": "22732ec9-ab60-4e1b-fd1c-778be5710790",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "print(predicted_ratings.shape)"
      ],
      "execution_count": 90,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "(1628, 9)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "y1IGrVJBaKwb",
        "outputId": "6a5c70e9-c5b5-4364-ec36-2587c40559a4",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "print(predicted_ratings)"
      ],
      "execution_count": 91,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "[[6.28711879e-01 3.71125787e-01 1.93846718e-05 ... 2.48171236e-05\n",
            "  2.07571484e-05 3.11595759e-05]\n",
            " [5.16196430e-01 4.83636826e-01 2.06636632e-05 ... 2.40022491e-05\n",
            "  2.14833890e-05 3.09596326e-05]\n",
            " [8.92104924e-01 1.07851624e-01 4.90856564e-06 ... 8.67088238e-06\n",
            "  4.84645898e-06 9.25974837e-06]\n",
            " ...\n",
            " [6.53564811e-01 3.46285373e-01 1.90432311e-05 ... 2.25746426e-05\n",
            "  1.92296520e-05 2.91551714e-05]\n",
            " [5.77207983e-01 4.22657400e-01 1.69154791e-05 ... 1.97136451e-05\n",
            "  1.75365039e-05 2.56826916e-05]\n",
            " [6.86957419e-01 3.12936485e-01 1.36032540e-05 ... 1.61753997e-05\n",
            "  1.37795878e-05 2.07246703e-05]]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "4Uqrx92hd1Yl"
      },
      "source": [
        "Output is of shape (1628, 9). We got probability of each possible rating from 1 to 5. We can extract specific rating which user would have given to a movie but it is not useful for these recommendations now."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "KNOAYhR0e6-h",
        "outputId": "5f6aea9d-d39f-47f5-99c2-6d6fda8e047b",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "predicted_ratings = np.max(predicted_ratings, axis=1)\n",
        "predicted_ratings"
      ],
      "execution_count": 98,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([0.6287119, 0.5161964, 0.8921049, ..., 0.6535648, 0.577208 ,\n",
              "       0.6869574], dtype=float32)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 98
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "X_AitEdxe7UB",
        "outputId": "ff5bee9d-73ab-4d84-f94d-c3ded15bf273",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "predicted_ratings.shape"
      ],
      "execution_count": 99,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(1628,)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 99
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "nMyRRTncgMbf"
      },
      "source": [
        "Index of ratings sorted by descending order."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ouBCeCapf-UK",
        "outputId": "a0fd1203-cead-4ceb-9035-5a125a967cb3",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "sorted_index = np.argsort(predicted_ratings)[::-1]\n",
        "print(sorted_index)"
      ],
      "execution_count": 110,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "[1445  135  962 ... 1030  460  159]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "1wKHCeFTkROY"
      },
      "source": [
        "**Movie names have been extracted from the available indices we got.**"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "p6KxPoScf-d6",
        "outputId": "35e94fd4-35e0-4492-a579-7fa51df0a76b",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "recommended_movies = item_enc.inverse_transform(sorted_index)\n",
        "recommended_movies"
      ],
      "execution_count": 124,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array(['Sword in the Stone, The (1963)', 'Baton Rouge (1988)',\n",
              "       'Meet Wally Sparks (1997)', ..., 'My Favorite Year (1982)',\n",
              "       'English Patient, The (1996)', 'Beverly Hillbillies, The (1993)'],\n",
              "      dtype=object)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 124
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HaKPES74keEW"
      },
      "source": [
        "## Movies recommended with the help of Softmax Deep Neural Networks"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "CIIumPFPf-mS",
        "outputId": "0c5edf6d-6ac6-4a14-e669-7b9ddf8b65a2",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "from pprint import pprint\n",
        "pprint(list(recommended_movies[:20]))"
      ],
      "execution_count": 130,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "['Sword in the Stone, The (1963)',\n",
            " 'Baton Rouge (1988)',\n",
            " 'Meet Wally Sparks (1997)',\n",
            " 'Grosse Fatigue (1994)',\n",
            " 'In the Line of Duty 2 (1987)',\n",
            " 'Conspiracy Theory (1997)',\n",
            " 'Red Firecracker, Green Firecracker (1994)',\n",
            " 'Striking Distance (1993)',\n",
            " 'Two or Three Things I Know About Her (1966)',\n",
            " 'Phat Beach (1996)',\n",
            " 'Diva (1981)',\n",
            " 'Getaway, The (1994)',\n",
            " 'Jaws 2 (1978)',\n",
            " 'Welcome to the Dollhouse (1995)',\n",
            " 'Basic Instinct (1992)',\n",
            " 'Saint, The (1997)',\n",
            " 'Critical Care (1997)',\n",
            " 'Jude (1996)',\n",
            " 'Mediterraneo (1991)',\n",
            " 'Month by the Lake, A (1995)']\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "SoXBhPMiku38"
      },
      "source": [
        "## Summing up the entire code into a recommender system function:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "MwBUv7TlkuDn"
      },
      "source": [
        "def recommender_system(user_id, model, n_movies):\n",
        "\n",
        "  print(\"\")\n",
        "  print(\"Movie seen by the User:\")\n",
        "  pprint(list(refined_dataset[refined_dataset['user id'] == user_id]['movie title']))\n",
        "  print(\"\")\n",
        "\n",
        "  encoded_user_id = user_enc.transform([user_id])\n",
        "\n",
        "  seen_movies = list(refined_dataset[refined_dataset['user id'] == user_id]['movie'])\n",
        "  unseen_movies = [i for i in range(min(refined_dataset['movie']), max(refined_dataset['movie'])+1) if i not in seen_movies]\n",
        "  model_input = [np.asarray(list(encoded_user_id)*len(unseen_movies)), np.asarray(unseen_movies)]\n",
        "  predicted_ratings = model.predict(model_input)\n",
        "  predicted_ratings = np.max(predicted_ratings, axis=1)\n",
        "  sorted_index = np.argsort(predicted_ratings)[::-1]\n",
        "  recommended_movies = item_enc.inverse_transform(sorted_index)\n",
        "  print(\"---------------------------------------------------------------------------------\")\n",
        "  print(\"Top \"+str(n_movies)+\" Movie recommendations for the User \"+str(user_id)+ \" are:\")\n",
        "  pprint(list(recommended_movies[:n_movies]))"
      ],
      "execution_count": 141,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "-qAd6yrukuK_",
        "outputId": "da16c604-2b70-4da3-eff1-9e01d38e4db7",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "print(\"Enter user id\")\n",
        "user_id= int(input())\n",
        "\n",
        "print(\"Enter number of movies to be recommended:\")\n",
        "n_movies = int(input())\n",
        "recommender_system(user_id,model,n_movies)\n"
      ],
      "execution_count": 139,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Enter user id\n",
            "307\n",
            "Enter number of movies to be recommended:\n",
            "15\n",
            "Movie seen by the User:\n",
            "['12 Angry Men (1957)',\n",
            " '2001: A Space Odyssey (1968)',\n",
            " 'Abyss, The (1989)',\n",
            " 'Alien (1979)',\n",
            " 'Apollo 13 (1995)',\n",
            " 'Boot, Das (1981)',\n",
            " 'Brady Bunch Movie, The (1995)',\n",
            " 'Braveheart (1995)',\n",
            " 'Brazil (1985)',\n",
            " 'Casablanca (1942)',\n",
            " 'Close Shave, A (1995)',\n",
            " 'Contact (1997)',\n",
            " 'E.T. the Extra-Terrestrial (1982)',\n",
            " 'Empire Strikes Back, The (1980)',\n",
            " 'English Patient, The (1996)',\n",
            " 'Englishman Who Went Up a Hill, But Came Down a Mountain, The (1995)',\n",
            " 'Escape from L.A. (1996)',\n",
            " 'Fargo (1996)',\n",
            "...\n",
            "...\n",
            " 'Sex, Lies, and Videotape (1989)',\n",
            " 'Shadowlands (1993)',\n",
            " 'Shawshank Redemption, The (1994)',\n",
            " 'Shining, The (1980)',\n",
            " 'Sneakers (1992)',\n",
            " 'Snow White and the Seven Dwarfs (1937)',\n",
            " 'Sound of Music, The (1965)',\n",
            " 'Stand by Me (1986)',\n",
            " 'Star Trek III: The Search for Spock (1984)',\n",
            " 'Star Trek IV: The Voyage Home (1986)',\n",
            " 'Star Trek: The Motion Picture (1979)',\n",
            " 'Star Trek: The Wrath of Khan (1982)',\n",
            " 'Star Wars (1977)',\n",
            " 'Stargate (1994)',\n",
            " 'Tank Girl (1995)',\n",
            " 'Terminator, The (1984)',\n",
            " 'This Is Spinal Tap (1984)',\n",
            " 'Titanic (1997)',\n",
            " 'To Kill a Mockingbird (1962)',\n",
            " 'Top Gun (1986)',\n",
            " 'Toy Story (1995)',\n",
            " 'Wallace & Gromit: The Best of Aardman Animation (1996)',\n",
            " 'Wizard of Oz, The (1939)',\n",
            " 'Wrong Trousers, The (1993)']\n",
            "\n",
            "--------------------------------------------------------------\n",
            "Top 15 Movie recommendations for the User 307 are:\n",
            "['Speed 2: Cruise Control (1997)',\n",
            " 'Houseguest (1994)',\n",
            " 'Batman & Robin (1997)',\n",
            " 'Magic Hour, The (1998)',\n",
            " \"Devil's Advocate, The (1997)\",\n",
            " 'Gone with the Wind (1939)',\n",
            " 'Cobb (1994)',\n",
            " 'Cool Runnings (1993)',\n",
            " 'Independence Day (ID4) (1996)',\n",
            " 'Smoke (1995)',\n",
            " 'Once Were Warriors (1994)',\n",
            " 'True Romance (1993)',\n",
            " 'Red Rock West (1992)',\n",
            " 'Third Man, The (1949)',\n",
            " 'MatchMaker, The (1997)']\n",
            "--------------------------------------------------------------\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "tsUcbpEfktjP"
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "bwlRm9Hie7Fd"
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "MjLN1Dd_m14L"
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "XkbzKD0Om2VM"
      },
      "source": [
        "# Rough Work"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ICIiS-jwfCdL",
        "outputId": "ec9052d4-c5f9-46d8-a186-a24463234218",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "a = np.asarray([[2,3,14,6],[3,5,7,2],[6,8,4,1]])\n",
        "a, a.shape"
      ],
      "execution_count": 102,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(array([[ 2,  3, 14,  6],\n",
              "        [ 3,  5,  7,  2],\n",
              "        [ 6,  8,  4,  1]]), (3, 4))"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 102
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1Sv1WMgdfOkj",
        "outputId": "9750cdcc-0663-41c8-a8d4-81c22815d339",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "b=np.max(a, axis=1)\n",
        "b, b.shape"
      ],
      "execution_count": 103,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(array([14,  7,  8]), (3,))"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 103
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "67xRASFNfu2p",
        "outputId": "1b812c33-04e1-477e-97bd-d626fa4a4669",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "np.argsort(b)[::-1]"
      ],
      "execution_count": 106,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([0, 2, 1])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 106
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "PfTQmi93Q7X4",
        "outputId": "fd48d1c0-ef59-4e6c-b78c-98b2acfb37db",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "\n",
        "user_enc.transform([1])"
      ],
      "execution_count": 56,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([0])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 56
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "5VPBNYx3Rlub",
        "outputId": "6edd0f33-c3a5-4296-a744-6e2ccca4fbb0",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "max(refined_dataset['user'])"
      ],
      "execution_count": 52,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "942"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 52
        }
      ]
    }
  ]
}
